<?php

namespace App\Jobs;

use App\Http\Controllers\RedisServiceController;
use App\Http\Controllers\Wechat\TurnActivityDrawController;
use App\Models\TurnActivity;
use App\Models\TurnActivityGift;
use App\Models\TurnActivityGiftConfig;
use App\Models\TurnActivityUserGift;
use App\Models\TurnActivityUserPrize;
use App\Models\TurnActivityUserUsePrizeRecord;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

/**
 * 在线抽奖活动抽奖队列
 */
class TurnActivityDrawJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;


    public $turn_red_transfer_key = 're_turn_red_transfer';
    public static $percent_way = 1; //概率方式   1 单个奖品独立概率方式    2 所以奖品总概率形式
    public static $gift_max_number_day = 100; //礼物每日发送奖品最大数量
    public static $red_max_number_day = 500; //红包每日发送奖品最大数量
    public static $user_gift_number_day = 1; //用户当日可获得多少实物礼品
    public static $user_red_number_day = 5; //用户当日可获得多少红包礼品

    public $key;
    public $value;

    /**
     * 任务最大尝试次数。
     *
     * @var int
     */
    public $tries = 3;   //这里写了，程序会自动尝试执行 几次
    /**
     * 任务运行的超时时间。
     *
     * @var int
     */
    public $timeout = 180;


    /**
     * Create a new job instance.
     *
     * @return void
     * //执行监听程序（php artisan queue:listen），会自动把之前写入队列的参数拿出，放到对应位置，这里只是个写入对应的程序参数对应，但是他们不是同步执行的
     */
    public function __construct($key = null, $value = null)
    {
        $this->key = $key;
        $this->value = $value;
    }

    /**
     * Execute the job.
     *
     * @return void
     * 
     //执行 $tries 次失败后，会自动 存到数据表 表前缀_failed_jobs  中

      $value =  $data = [
            'act_id' => $this->request->act_id,
            'user_guid' => $this->request->token,
            'order_key' => $this->turn_activity_draw_key,
            'order_id' => $order_id,
            'create_time' => date("Y-m-d H:i:s"),
            'date' => date("Y-m-d"),
            'hour' => date("H")
        ];

     */
    public function handle()
    {
        $turnActivityDrawController = new TurnActivityDrawController();
        if (empty($this->value['order_key']) || $this->value['order_key'] != $turnActivityDrawController->turn_activity_draw_key) {
            return false; //不是在线抽奖抽奖类作品，不处理
        }

        $turnActivityUserUsePrizeRecord = new TurnActivityUserUsePrizeRecord();
        $turnActivityUserGiftModel = new TurnActivityUserGift();
        $activityModel = new TurnActivity();

        $redisObj = RedisServiceController::getInstance();

        $act_id = $this->value['act_id'];
        $user_guid = $this->value['user_guid'];
        $result = false; //中奖数据
        DB::beginTransaction();
        try {
            //进行抽奖操作
            $act_info = $activityModel->detail($act_id);
            if (empty($act_info)) {
                throw new Exception('参数错误');
            }

            //判断是否有抽奖次数
            $isHavePrizeNumber = $turnActivityUserUsePrizeRecord->getSurplusPrizeNumber($act_id, $user_guid, $act_info);
            if ($isHavePrizeNumber <= 0) {
                throw new Exception('无抽奖次数');
            }

            //抽奖计算概率
            //获取总概率
            $total_gift_config = TurnActivityGiftConfig::where('act_id', $act_id)->first();
            if (!empty($total_gift_config)) {
                if ($total_gift_config['percent_way']) self::$percent_way = $total_gift_config['percent_way']; //概率方式   1 单个奖品独立概率方式    2 所以奖品总概率形式
                if ($total_gift_config['gift_max_number_day']) self::$gift_max_number_day = $total_gift_config['gift_max_number_day']; //礼物每日发送奖品最大数量
                if ($total_gift_config['red_max_number_day']) self::$red_max_number_day = $total_gift_config['red_max_number_day']; //红包每日发送奖品最大数量
                if ($total_gift_config['user_gift_number_day']) self::$user_gift_number_day = $total_gift_config['user_gift_number_day']; //用户当日可获得多少实物礼品
                if ($total_gift_config['user_red_number_day']) self::$user_red_number_day = $total_gift_config['user_red_number_day']; //用户当日可获得多少红包礼品
            }

            $red_win = false; //获取红包机会
            $gift_win = false; //获取礼物机会

            //获取用户今日是否可以获取红包
            $turn_activity_gift_type = config('other.turn_activity_gift_type');
            if (in_array(1, $turn_activity_gift_type)) {
                $day_red_info = $turnActivityUserGiftModel->isDayWinChance($act_id, $user_guid, 1);
            } else {
                $day_red_info = false;
            }
            if (in_array(2, $turn_activity_gift_type)) {
                $day_gift_info = $turnActivityUserGiftModel->isDayWinChance($act_id, $user_guid, 2);
            } else {
                $day_gift_info = false;
            }
            if ($day_red_info) {
                //获取时间段是否可以中红包
                $time_quantum_red_info = $turnActivityUserGiftModel->isTimeQuantumWinChance($act_id, $user_guid, 1);
                $red_win = $time_quantum_red_info ? true : false;
            }

            if ($day_gift_info) {
                //获取时间段是否可以中礼物
                $time_quantum_gift_info = $turnActivityUserGiftModel->isTimeQuantumWinChance($act_id, $user_guid, 2);
                $gift_win = $time_quantum_gift_info ? true : false;
            }
            //至少中一个的逻辑
            if ($red_win || $gift_win) {
                if ($red_win && $gift_win) {
                    $type = 0; //所有都可以中
                } elseif ($gift_win) {
                    $type = 2; //只能中礼物
                } else {
                    $type = 1; //只能中红包
                }
                //获取所有可以中奖的礼物
                $turnActivityGiftModel = new TurnActivityGift();
                $gift_data_all = $turnActivityGiftModel->getSurplusGift($act_id, $type, $turnActivityUserUsePrizeRecord->gift_grant_start_time, $turnActivityUserUsePrizeRecord->gift_grant_end_time);
                //没有礼物直接未中奖
                if (!empty($gift_data_all)) {
                    $commonDrawJob = new CommonDrawJob();
                    $result = $commonDrawJob->probabilityDraw($gift_data_all, self::$percent_way);
                }
            }
            //增加抽奖表记录
            $use_prize_record_id = TurnActivityUserUsePrizeRecord::insertGetId([
                'order_id' => $this->value['order_id'],
                'act_id' => $this->value['act_id'],
                'user_guid' => $this->value['user_guid'],
                'date' => date('Y-m-d'),
                'status' => !empty($result) ? 1 : 2, //是否中奖  1 中奖  2 未中奖
                'create_time' => $this->value['create_time'],
                'change_time' => date('Y-m-d H:i:s'),
            ]);

            //中奖逻辑
            if (!empty($result)) {
                //增加用户奖品
                $turn_activity_user_gift_id = $turnActivityUserGiftModel->insertGetId([
                    'act_id' => $act_id,
                    'user_guid' => $user_guid,
                    'gift_id' => $result['id'],
                    'price' => $result['type'] == 1 ? $result['price'] : '',
                    'order_id' => $this->value['order_id'],
                    'use_prize_record_id' => $use_prize_record_id,
                    'state' => $result['type'] == 1 ? 1 : ($result['way'] == 1 ? 6 : 3),
                    'date' => date('Y-m-d'),
                    'hour' => date('H'),
                    'type' => $result['type'],
                    'create_time' => date('Y-m-d H:i:s')
                ]);

                //如果是红包，还要进行转账操作（写入队列，进行转账）
                if ($result['type'] == 1) {
                    //写入红包队列
                    $data['user_gift_id'] = $turn_activity_user_gift_id;
                    $data['act_name'] = $act_info['title'];
                    $queue_id = dispatch(new TurnActivityTransferJob($this->turn_red_transfer_key, $data))->onQueue($this->turn_red_transfer_key); //执行完后就不用管了，也不用管另外一个控制器怎么拿的到这些参数，各写各的逻辑即可
                    //   $queue_id = $this->dispatch(new TurnActivityTransferJob('turn_red_transfer', $data))->onQueue('turn_red_transfer'); //执行完后就不用管了，也不用管另外一个控制器怎么拿的到这些参数，各写各的逻辑即可
                    if (!$queue_id) {
                        throw new Exception('未中奖');
                    }
                }
            }

            //删除用户正在抽奖中，可以再次抽奖
            $redisObj->delRedisValue($this->value['order_key'] . $this->value['user_guid']);
            //    $redisObj->delRedisValue($this->value['order_key'] . $this->value['order_id']);//临时打开，在获取结果是删除

            DB::commit();
            return '抽奖完成';
        } catch (Exception $e) {
            //删除用户正在抽奖中，可以再次抽奖
            $redisObj->delRedisValue($this->value['order_key'] . $this->value['user_guid']);
            //   $redisObj->delRedisValue($this->value['order_key'] . $this->value['order_id']);

            Log::channel('handcmdlog')->info('在线抽奖抽奖失败：' . $e->getMessage() . $e->getFile() . $e->getLine());

            DB::rollBack();
            return '抽奖失败：' . $e->getMessage();
        }
    }



    //失败多次，就是没中奖
    public function failed()
    {
        dump('failed'); //程序报错才会走这里，try cache 拦截后，不会走这里，程序会以执行成功处理
    }
}





